gusucode.com > VC++ 基于IE内核功能很齐全的浏览器(支持多标签)-源码程序 > VC++ 基于IE内核功能很齐全的浏览器(支持多标签)-源码程序/code/Explorer/BBHyperLink.cpp
//Download by http://www.NewXing.com // BBHyperLink.cpp : implementation file // #include "stdafx.h" #include "BBHyperLink.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CBBHyperLink #define TOOLTIP_ID 1 //设置风格位操作 #define SETBITS(dw, bits) (dw |= bits) //去掉风格位操作 #define CLEARBITS(dw, bits) (dw &= ~(bits)) //判断风格位操作 #define BITSET(dw, bit) (((dw) & (bit)) != 0L) ///////////////////////////////////////////////////////////////////////////// // CBBHyperLink const DWORD CBBHyperLink::STYLEUNDERLINE = 0x00000001; // 下划线 const DWORD CBBHyperLink::STYLEUSEHOVER = 0x00000002; // 鼠标的掠过颜色风格 const DWORD CBBHyperLink::STYLEAUTOSIZE = 0x00000004; // 自动调整大小 const DWORD CBBHyperLink::STYLEDOWNCLICK = 0x00000008; // 鼠标按下代表单击风格 const DWORD CBBHyperLink::STYLEGETFOCUSONCLICK = 0x00000010; // 单击时候得到光标 const DWORD CBBHyperLink::STYLENOHANDCURSOR = 0x00000020; // 没有设置光标 const DWORD CBBHyperLink::STYLENOACTIVECOLOR = 0x00000040; // 没有活动时设置颜色 //默认的颜色 COLORREF CBBHyperLink::m_crLinkColor = RGB(0, 0, 255); COLORREF CBBHyperLink::m_crActiveColor = RGB(0, 128, 128); COLORREF CBBHyperLink::m_crVisitedColor = RGB(128, 0, 128); COLORREF CBBHyperLink::m_crHoverColor = RGB(255, 0, 0 ); HCURSOR CBBHyperLink::m_hLinkCursor = NULL; CBBHyperLink::CBBHyperLink() { m_bOverControl = FALSE; // 光标不在控件上 m_bVisited = FALSE; // 可见 m_bLinkActive = FALSE; // 活动 m_strURL.Empty(); // URL // 设置默认的风格 m_dwStyle = STYLEUNDERLINE|STYLEAUTOSIZE|STYLEGETFOCUSONCLICK; } CBBHyperLink::~CBBHyperLink() { m_Font.DeleteObject(); } IMPLEMENT_DYNAMIC(CBBHyperLink, CStatic) BEGIN_MESSAGE_MAP(CBBHyperLink, CStatic) //{{AFX_MSm_MAP(CBBHyperLink) ON_WM_CTLCOLOR_REFLECT() ON_WM_SETCURSOR() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_WM_KEYDOWN() ON_WM_NCHITTEST() ON_WM_LBUTTONDOWN() //}}AFX_MSm_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CBBHyperLink message handlers BOOL CBBHyperLink::PreTranslateMessage(MSG* pMsg) { m_ToolTip.RelayEvent(pMsg); return CStatic::PreTranslateMessage(pMsg); } void CBBHyperLink::PreSubclassWindow() { // 如果URL为空,以显示文本为连接对象 if (m_strURL.IsEmpty()) GetWindowText(m_strURL); //检查是否为空 CString strWndText; GetWindowText(strWndText); if (strWndText.IsEmpty()) { //ASSERT(!m_strURL.IsEmpty()); CStatic::SetWindowText(m_strURL); } //得到字体 CFont* pFont = GetFont(); if (pFont != NULL) { LOGFONT lf; pFont->GetLogFont(&lf); lf.lfUnderline = BITSET(m_dwStyle, STYLEUNDERLINE); if (m_Font.CreateFontIndirect(&lf)) CStatic::SetFont(&m_Font); //调整窗口的大小,以适应字体的全部可见 AdjustWindow(); } else { //如果没有得到字体,说明本控件不是一个Text类型的, //把其设置成自动伸缩 CLEARBITS(m_dwStyle,STYLEAUTOSIZE); } if (!BITSET(m_dwStyle,STYLENOHANDCURSOR)) SetDefaultCursor(); //提示 CRect rect; GetClientRect(rect); m_ToolTip.Create(this); m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID); CStatic::PreSubclassWindow(); } //设置字体和颜色 HBRUSH CBBHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) { ASSERT(nCtlColor == CTLCOLOR_STATIC); if (m_bOverControl && BITSET(m_dwStyle,STYLEUSEHOVER)) { pDC->SetTextColor(m_crHoverColor); } else if (!BITSET(m_dwStyle,STYLENOACTIVECOLOR) && m_bLinkActive) { pDC->SetTextColor(m_crActiveColor); } else if (m_bVisited) { pDC->SetTextColor(m_crVisitedColor); } else { pDC->SetTextColor(m_crLinkColor); } pDC->SetBkMode(TRANSPARENT); return (HBRUSH)GetStockObject(NULL_BRUSH); } void CBBHyperLink::OnMouseMove(UINT nFlags, CPoint point) { if (m_bOverControl) // 当前在 { CRect rect; GetClientRect(rect); if (!rect.PtInRect(point)) { m_bOverControl = FALSE; ReleaseCapture(); Invalidate(); return; } } else // 光标已经离开 { m_bOverControl = TRUE; Invalidate(); SetCapture(); } } //通常,如果没有SS_NOTIFY,Static控件得不到到鼠标事件, //本函数完成了与SS_NOTIFY //的效果,但在调用OnCtlColor时打开SS_NOTIFY更可靠,因为在Bitamap风格的Static中没有 //发送WM_CTLCOLOR的消息 UINT CBBHyperLink::OnNcHitTest(CPoint point) { return HTCLIENT; } void CBBHyperLink::OnLButtonDown(UINT nFlags, CPoint point) { if (BITSET(m_dwStyle,STYLEGETFOCUSONCLICK)) { SetFocus(); } if (BITSET(m_dwStyle,STYLEDOWNCLICK)) { FollowLink(); } m_bLinkActive = TRUE; } void CBBHyperLink::OnLButtonUp(UINT nFlags, CPoint point) { if (m_bLinkActive && !BITSET(m_dwStyle,STYLEDOWNCLICK)) FollowLink(); } BOOL CBBHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if (m_hLinkCursor) { ::SetCursor(m_hLinkCursor); return TRUE; } return FALSE; } void CBBHyperLink::OnSetFocus(CWnd* pOldWnd) { m_bLinkActive = TRUE; Invalidate(); // Repaint to set the focus } void CBBHyperLink::OnKillFocus(CWnd* pNewWnd) { // Assume that control lost focus = mouse out // this avoid troubles with the Hover color m_bOverControl = FALSE; m_bLinkActive = FALSE; Invalidate(); // Repaint to unset the focus } void CBBHyperLink::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { //空格 if (nChar == VK_SPACE) { FollowLink(); } else { CStatic::OnKeyDown(nChar, nRepCnt, nFlags); } } ///////////////////////////////////////////////////////////////////////////// // CBBHyperLink operations void CBBHyperLink::SetColors( COLORREF crLinkColor, COLORREF crActiveColor, COLORREF crVisitedColor, COLORREF crHoverColor /* = -1 */) { m_crLinkColor = crLinkColor; m_crActiveColor = crActiveColor; m_crVisitedColor = crVisitedColor; if (crHoverColor == -1) m_crHoverColor = ::GetSysColor(COLOR_HIGHLIGHT); else m_crHoverColor = crHoverColor; } void CBBHyperLink::GetColors(COLORREF &crLink,COLORREF &crActive,COLORREF &crVisited,COLORREF &crHover) { crLink=m_crLinkColor; crActive = m_crActiveColor; crVisited = m_crVisitedColor; crHover = m_crHoverColor; } void CBBHyperLink::SetLinkCursor(HCURSOR hCursor) { ASSERT(hCursor != NULL); m_hLinkCursor = hCursor; if (m_hLinkCursor == NULL) SetDefaultCursor(); } HCURSOR CBBHyperLink::GetLinkCursor() { return m_hLinkCursor; } BOOL CBBHyperLink:: ModifyLinkStyle(DWORD dwRemove, DWORD dwAdd, BOOL bApply /* =TRUE */) { if ((dwRemove & dwAdd) != 0L) return FALSE; CLEARBITS(m_dwStyle, dwRemove); SETBITS(m_dwStyle, dwAdd); if (bApply && ::IsWindow(GetSafeHwnd())) { if (BITSET(dwAdd,STYLEUNDERLINE) || BITSET(dwRemove,STYLEUNDERLINE)) SwitchUnderline(); if (BITSET(dwAdd,STYLEAUTOSIZE)) AdjustWindow(); if (BITSET(dwRemove,STYLEUSEHOVER)) Invalidate(); } return TRUE; } DWORD CBBHyperLink::GetLinkStyle() const { return m_dwStyle; } void CBBHyperLink::SetURL(CString strURL) { m_strURL = strURL; if (::IsWindow(GetSafeHwnd())) { ShowWindow(SW_HIDE); AdjustWindow(); m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID); ShowWindow(SW_SHOW); } } CString CBBHyperLink::GetURL() const { return m_strURL; } void CBBHyperLink::SetWindowText(LPCTSTR lpszText) { ASSERT(lpszText != NULL); if (::IsWindow(GetSafeHwnd())) { ShowWindow(SW_HIDE); CStatic::SetWindowText(lpszText); AdjustWindow(); ShowWindow(SW_SHOW); } } void CBBHyperLink::SetFont(CFont* pFont) { ASSERT(::IsWindow(GetSafeHwnd())); ASSERT(pFont != NULL); ShowWindow(SW_HIDE); LOGFONT lf; pFont->GetLogFont(&lf); m_Font.DeleteObject(); m_Font.CreateFontIndirect(&lf); CStatic::SetFont(&m_Font); AdjustWindow(); ShowWindow(SW_SHOW); } void CBBHyperLink::SwitchUnderline() { LOGFONT lf; CFont* pFont = GetFont(); if (pFont != NULL) { pFont->GetLogFont(&lf); lf.lfUnderline = BITSET(m_dwStyle,STYLEUNDERLINE); m_Font.DeleteObject(); m_Font.CreateFontIndirect(&lf); SetFont(&m_Font); } } //调整窗口的大小,以适应文字的大小 void CBBHyperLink::AdjustWindow() { ASSERT(::IsWindow(GetSafeHwnd())); if (!BITSET(m_dwStyle,STYLEAUTOSIZE)) return; CRect rcWnd; GetWindowRect(rcWnd); //父窗口先转换 CWnd* pParent = GetParent(); if (pParent) pParent->ScreenToClient(rcWnd); CRect rcClient; GetClientRect(rcClient); // 计算边框 int borderWidth = rcWnd.Width() - rcClient.Width(); int borderHeight = rcWnd.Height() - rcClient.Height(); // 得到字体的尺寸 CString strWndText; GetWindowText(strWndText); CDC* pDC = GetDC(); CFont* pOldFont = pDC->SelectObject(&m_Font); CSize Extent = pDC->GetTextExtent(strWndText); pDC->SelectObject(pOldFont); ReleaseDC(pDC); //得到字体的对方式 DWORD dwStyle = GetStyle(); if (BITSET(dwStyle, SS_CENTERIMAGE)) { rcWnd.DeflateRect(0, (rcWnd.Height() - Extent.cy) / 2); } else { rcWnd.bottom = rcWnd.top + Extent.cy; } if (BITSET(dwStyle, SS_CENTER)) { rcWnd.DeflateRect((rcWnd.Width() - Extent.cx) / 2, 0); } else if (BITSET(dwStyle,SS_RIGHT)) { rcWnd.left = rcWnd.right - Extent.cx; } else // SS_LEFT { rcWnd.right = rcWnd.left + Extent.cx; } MoveWindow(rcWnd.left, rcWnd.top, rcWnd.Width() + borderWidth, rcWnd.Height() + borderHeight); } void CBBHyperLink::SetVisited(BOOL bVisited /* = TRUE */) { m_bVisited = bVisited; } BOOL CBBHyperLink::IsVisited() const { return m_bVisited; } ///////////////////////////////////////////////////////////////////////////// // CBBHyperLink implementation // 从WIn32hlp中得到默认的手形光标 void CBBHyperLink::SetDefaultCursor() { //如果仅在Win2000中可以用 //HCURSOR hHandCursor=::LoadCursor(NULL,IDC_HAND); //m_hLinkCursor = CopyCursor(hHandCursor); //return; //否则用 if (m_hLinkCursor == NULL) { CString strWndDir; GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH); strWndDir.ReleaseBuffer(); strWndDir += _T("\\winhlp32.exe"); HMODULE hModule = LoadLibrary(strWndDir); if (hModule) { HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106)); if (hHandCursor) m_hLinkCursor = CopyCursor(hHandCursor); } FreeLibrary(hModule); } } HINSTANCE CBBHyperLink::GotoURL(LPCTSTR url, int showcmd) { HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd); return result; } // 激活连接控件 void CBBHyperLink::FollowLink() { int result = (int) GotoURL(m_strURL, SW_SHOW); if (result <= HINSTANCE_ERROR) { MessageBeep(MB_ICONEXCLAMATION); } else { m_bVisited = TRUE; Invalidate(); } }